#ifndef A_COMPARE_H_
#define A_COMPARE_H_


//! A mixin of equality operators.
/*!
    This class extends the operator set of a derived (\em owner) class
    with operators == and !=. More precise, it allows to use compare
    syntax \c{b == a}, \c{a != b} and \c{b != a}, when the client code
    of the owner class provides only \c{a == b}. The corresponding
    operators is defined in the mixin eq_neq_comparable in the following
    way:
    \li \c{b == a} if and only if \c{a == b},
    \li \c{a != b} if and only if \c{!(a == b)},
    \li \c{b != a} if and only if \c{!(a == b)}.
    
    Note that \c a must be an object of the owner class, and \c b can has
    any type. The base syntax \c{a == b} is generated by the operator ==,
    which must be defined in the owner class. The owner class can define
    several overloaded versions of the operator == with the first argument
    of type \c owner. It also can override some operators, which was
    defined in the mixin, to reach another behavior of them.
    
    \tparam owner Derived class, to which the mixin will applied.
    
    \tparam boolean A type of the result of operators == and !=. It is
    \c bool by default, but a user can specify another type for another
    kind of logic (e.g. three-valued logic or fuzzy logic).
    
    Suppose there is a class \c integer which emulates integral
    numbers. An author of the class defined two equality operators:
    for compare two \c{integer}s and for compare an \c integer with
    a native \c int. Other operators are provided by the mixin.
    \code
        class integer
            : public eq_neq_comparable<integer>
        {
            ... // Some implementing stuff
            
        public:
            bool operator==( const integer & that ) const { ... }
            bool operator==( int that ) const { ... }
        };
    \endcode
    A user of the \c integer class can use the following syntax:
    \code
        integer one(1), two(2);
        
        // Operators defined in the integer class
        one == two; // Equivalent to one.operator==(two)
        one == 2;   // Equivalent to one.operator==(2)
        
        // Operators defined by the mixin
        one != two; // Equivalent to !one.operator==(two)
        one != 2;   // Equivalent to !one.operator==(2)
        1 == two;   // Equivalent to two.operator==(1)
        1 != two;   // Equivalent to !two.operator==(1)
    \endcode
*/
template
<
    class owner,
    class boolean = bool
>
class eq_neq_comparable
{
protected:
    //! Default constructor.
    /*!
        The constructor does nothing, because the mixin has no data
        members. It is protected to prevent operating the mixin
        separately the owner object.
    */
    eq_neq_comparable();
    
    
    //! Copy constructor.
    /*!
        The constructor does nothing, because the mixin has no data
        members. The only purpose of this constructor is supporting
        of auto-generated copy constructor of derived classes.
        You shouldn't call this constructor in manually written
        constructors; use default constructor instead. The constructor
        is protected to prevent operating the mixin separately
        the owner object.
    */
    eq_neq_comparable( eq_neq_comparable const & );
    
    
    //! Destructor.
    /*!
        The destructor is protected to prevent operating the mixin
        separately the owner object.
    */
    ~eq_neq_comparable();
    
    
public:
    //! Supplies syntax \c{a != b}, where \a a and \a b are both objects
    //! of the owner type.
    /*!
        Test of inequality of two owner objects \a self and \a that
        calls \c{self.operator==(that)} and returns the inverted result.
        This special case of inequality operation was introduced separately
    */
    friend boolean operator!=( const owner & self, const owner & that )
    {
        return !(self == that);
    }
    
    
    //! Supplies syntax \c{b == a}, where \a a is an owner object and \a b
    //! has an arbitrary type.
    /*!
        Test of equality of an object \a that (of any type) and an owner
        object \a self calls \c{self.operator==(that)} and returns
        the result. In other words, it simply swaps the arguments of the
        operator using the symmetry of an equality relation.
    */
    template< class other >
    friend boolean operator==( const other & that, const owner & self )
    {
        return (self == that);
    }
    
    
    //! Supplies syntax \c{a != b}, where \a a is an owner object and \a b
    //! has an arbitrary type.
    /*!
        Test of equality of an owner object \a self and an object \a that
        (of any type) calls \c{self.operator==(that)} and returns
        the inverted result. If \a that has an owner type, that the other
        function will be called.
    */
    template< class other >
    friend boolean operator!=( const owner & self, const other & that )
    {
        return !(self == that);
    }
    
    
    //! Supplies syntax \c{b != a}, where \a a is an owner object and \a b
    //! has an arbitrary type.
    /*!
        Test of equality of an object \a that (of any type) and an owner
        object \a self \c{self.operator==(that)} and returns the inverted
        result. In other words, it simply swaps the arguments of the
        operator using the symmetry of an inequality relation.
        If \a that has an owner type, that the other function
        will be called.
    */
    template< class other >
    friend boolean operator!=( const other & that, const owner & self )
    {
        return !(self == that);
    }
};


#endif /* A_COMPARE_H_ */
